﻿/*
<File>
	<Copyright>Copyright © 2007, Daniel Vaughan. All rights reserved.</Copyright>
	<License see="//License.txt"/>
	<Owner Name="Daniel Vaughan" Email="dbvaughan@gmail.com"/>
	<CreationDate>2007/11/19 20:00</CreationDate>
	<LastSubmissionDate>$Date: $</LastSubmissionDate>
	<Version>$Revision: $</Version>
</File>
*/

using System;
using System.Collections.Generic;
using System.Windows;

namespace DanielVaughan.Logging
{
	/// <summary>
	/// Managers all <see cref="ILog"/> instances.
	/// Is responsible for creation, and passing 
	/// on log events to subscribers.
	/// </summary>
	public static class LogManager
	{
		static readonly Dictionary<object, ILog> logList = new Dictionary<object, ILog>();
		static readonly object logListLock = new object();

		/// <summary>
		/// Gets or creates the log using the specified hostType
		/// to form the name of the log.
		/// </summary>
		/// <param name="hostType">Type of the host.</param>
		/// <returns>The log with the specified hostType.</returns>
		public static ILog GetLog(Type hostType)
		{
			ILog log;
			string name = Log.GetName(hostType);

			lock (logListLock)
			{
				if (logList.TryGetValue(name, out log))
				{
					return log;
				}
				log = new Log(hostType);
				logList[hostType] = log;
			}

			AttachLog(log);
			return log;
		}

		/// <summary>
		/// Gets or creates the log with the specified name.
		/// </summary>
		/// <param name="name">The name of the log.</param>
		/// <returns>The log with the specified name.</returns>
		public static ILog GetLog(string name)
		{
			ILog log;

			lock (logListLock)
			{
				if (logList.TryGetValue(name, out log))
				{
					return log;
				}
				log = new Log(name);
				logList[name] = log;
			}

			AttachLog(log);
			return log;
		}

		static void AttachLog(ILog log)
		{
			log.WriteRequested += log_LogEntrySendAttempt;
			log.LogEntrySent += log_LogEntrySent;
			log.InternalMessage += log_InternalError;
		}

		static void log_InternalError(object sender, InternalMessageEventArgs e)
		{
			OnError(sender, e);
		}

		static void DetachLog(ILog log)
		{
			log.WriteRequested -= log_LogEntrySendAttempt;
			log.LogEntrySent -= log_LogEntrySent;
			log.InternalMessage -= log_InternalError;
		}

		static void log_LogEntrySent(object sender, LogEventArgs e)
		{
			OnLogEntrySent(sender, e);
		}

		static void log_LogEntrySendAttempt(object sender, LogEventArgs e)
		{
			OnLogEntrySendAttempt(sender, e);
		}

		#region LogEntrySent
		static event EventHandler<LogEventArgs> logEntrySent;

		/// <summary>
		/// Occurs when any managed log raises its <see cref="ILog.LogEntrySent"/> event.
		/// This is a relay for such an event.
		/// </summary>
		public static event EventHandler<LogEventArgs> LogEntrySent
		{
			add
			{
				logEntrySent += value;
			}
			remove
			{
				logEntrySent -= value;
			}
		}

		static void OnLogEntrySent(object sender, LogEventArgs e)
		{
			if (logEntrySent != null)
			{
				logEntrySent(sender, e);
			}
		}
		#endregion

		#region WriteRequested
		static event EventHandler<LogEventArgs> writeRequested;

		/// <summary>
		/// Occurs when any managed log raises its <see cref="ILog.WriteRequested"/> event.
		/// This is a relay for such an event.
		/// </summary>
		public static event EventHandler<LogEventArgs> WriteRequested
		{
			add
			{
				writeRequested += value;
			}
			remove
			{
				writeRequested -= value;
			}
		}

		static void OnLogEntrySendAttempt(object sender, LogEventArgs e)
		{
			if (writeRequested != null)
			{
				writeRequested(sender, e);
			}
		}
		#endregion

		#region event Error

		static event EventHandler<InternalMessageEventArgs> error;

		public static event EventHandler<InternalMessageEventArgs> Error
		{
			add
			{
				error += value;
			}
			remove
			{
				error -= value;
			}
		}

		static void OnError(object sender, InternalMessageEventArgs e)
		{
			if (error != null)
			{
				error(sender, e);
			}
		}

		#endregion
	}
}
